From 754938ffb8de88179939eb313d9bf4da6ae7f134 Mon Sep 17 00:00:00 2001 From: Sondre Lefsaker Date: Fri, 1 May 2015 23:19:43 +0200 Subject: [PATCH] Add new subcommand `rustc`. - `cargo rustc` is starting out based on `cargo build` --- src/bin/cargo.rs | 1 + src/bin/rustc.rs | 95 +++++++++++++++++++++++++++++++++++++++ tests/test_cargo_rustc.rs | 41 +++++++++++++++++ tests/tests.rs | 1 + 4 files changed, 138 insertions(+) create mode 100644 src/bin/rustc.rs create mode 100644 tests/test_cargo_rustc.rs diff --git a/src/bin/cargo.rs b/src/bin/cargo.rs index a0490a96d..eb5ed1b65 100644 --- a/src/bin/cargo.rs +++ b/src/bin/cargo.rs @@ -75,6 +75,7 @@ macro_rules! each_subcommand{ ($mac:ident) => ({ $mac!(publish); $mac!(read_manifest); $mac!(run); + $mac!(rustc); $mac!(search); $mac!(test); $mac!(update); diff --git a/src/bin/rustc.rs b/src/bin/rustc.rs new file mode 100644 index 000000000..c7de721db --- /dev/null +++ b/src/bin/rustc.rs @@ -0,0 +1,95 @@ +use std::env; + +use cargo::ops::CompileOptions; +use cargo::ops; +use cargo::util::important_paths::{find_root_manifest_for_cwd}; +use cargo::util::{CliResult, CliError, Config}; + +#[derive(RustcDecodable)] +struct Options { + arg_pkgid: Option, + arg_opts: Option>, + flag_profile: Option, + flag_jobs: Option, + flag_features: Vec, + flag_no_default_features: bool, + flag_target: Option, + flag_manifest_path: Option, + flag_verbose: bool, + flag_release: bool, + flag_lib: bool, + flag_bin: Vec, + flag_example: Vec, + flag_test: Vec, + flag_bench: Vec, +} + +pub const USAGE: &'static str = " +Compile a package and all of its dependencies + +Usage: + cargo rustc [options] [] [--] [...] + +Options: + -h, --help Print this message + -p, --profile PROFILE The profile to compile for + -j N, --jobs N The number of jobs to run in parallel + --lib Build only this package's library + --bin NAME Build only the specified binary + --example NAME Build only the specified example + --test NAME Build only the specified test + --bench NAME Build only the specified benchmark + --release Build artifacts in release mode, with optimizations + --features FEATURES Features to compile for the package + --no-default-features Do not compile default features for the package + --target TRIPLE Target triple which compiles will be for + --manifest-path PATH Path to the manifest to fetch depednencies for + -v, --verbose Use verbose output + +The specified (defaults to the current package) will have all of its +dependencies compiled, and then the package itself will be compiled. This +command requires that a lockfile is available and dependencies have been +fetched. + +All of the trailing arguments are passed through to the *final* rustc +invocation, not any of the dependencies. + +Dependencies will not be recompiled if they do not need to be, but the package +specified will always be compiled. The compiler will receive a number of +arguments unconditionally such as --extern, -L, etc. Note that dependencies are +recompiled when the flags they're compiled with change, so it is not allowed to +manually compile a package's dependencies and then compile the package against +the artifacts just generated. +"; + +pub fn execute(options: Options, config: &Config) -> CliResult> { + debug!("executing; cmd=cargo-rustc; args={:?}", + env::args().collect::>()); + config.shell().set_verbose(options.flag_verbose); + + let root = try!(find_root_manifest_for_cwd(options.flag_manifest_path)); + let spec = options.arg_pkgid.as_ref().map(|s| &s[..]); + + let opts = CompileOptions { + config: config, + jobs: options.flag_jobs, + target: options.flag_target.as_ref().map(|t| &t[..]), + features: &options.flag_features, + no_default_features: options.flag_no_default_features, + spec: spec, + exec_engine: None, + mode: ops::CompileMode::Build, + release: options.flag_release, + filter: ops::CompileFilter::new(options.flag_lib, + &options.flag_bin, + &options.flag_test, + &options.flag_example, + &options.flag_bench), + }; + + ops::compile(&root, &opts).map(|_| None).map_err(|err| { + CliError::from_boxed(err, 101) + }) +} + + diff --git a/tests/test_cargo_rustc.rs b/tests/test_cargo_rustc.rs new file mode 100644 index 000000000..d119945a0 --- /dev/null +++ b/tests/test_cargo_rustc.rs @@ -0,0 +1,41 @@ +use std::path::MAIN_SEPARATOR as SEP; +use support::{execs, project, ProjectBuilder}; +use support::{COMPILING, RUNNING}; +use hamcrest::{assert_that}; + +fn setup() { +} + +fn verbose_output_for_lib(p: &ProjectBuilder) -> String { + format!("\ +{compiling} {name} v{version} ({url}) +{running} `rustc src{sep}lib.rs --crate-name {name} --crate-type lib -g \ + --out-dir {dir}{sep}target{sep}debug \ + --emit=dep-info,link \ + -L dependency={dir}{sep}target{sep}debug \ + -L dependency={dir}{sep}target{sep}debug{sep}deps` +", + running = RUNNING, compiling = COMPILING, sep = SEP, + dir = p.root().display(), url = p.url(), + name = "foo", version = "0.0.1") +} + +test!(build_lib_for_foo { + let p = project("foo") + .file("Cargo.toml", r#" + [package] + + name = "foo" + version = "0.0.1" + authors = ["wycats@example.com"] + "#) + .file("src/main.rs", r#" + fn main() {} + "#) + .file("src/lib.rs", r#" "#); + + assert_that(p.cargo_process("rustc").arg("--lib").arg("-v").arg("foo"), + execs() + .with_status(0) + .with_stdout(verbose_output_for_lib(&p))); +}); diff --git a/tests/tests.rs b/tests/tests.rs index 8be26db87..4d3ff6d77 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -48,6 +48,7 @@ mod test_cargo_profiles; mod test_cargo_publish; mod test_cargo_registry; mod test_cargo_run; +mod test_cargo_rustc; mod test_cargo_search; mod test_cargo_test; mod test_cargo_version; -- 2.30.2